home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / das / passc.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  7KB  |  259 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  PASSC.C
  9.  *
  10.  *  OPTIMIZATION PASS.    Note that the machine list can be sent to PASSG
  11.  *  without further modification whether or not this pass is run.  This
  12.  *  pass does simple optimization (-O1):
  13.  *
  14.  *    (1) remove MOVEM instructions of REG equates for 0 registers
  15.  *
  16.  *    (2) convert MOVEM instructions of REG equates for 1 register to MOVE
  17.  *
  18.  *    (3) convert Bcc l1 .. l1 Bra L2  to Bcc l2 (note that if a short
  19.  *        branch is forced the opt will not occur if l2 is out of range)
  20.  *
  21.  *    (4) check sizes branches, set size (b,w) for unsized branches
  22.  *        (this is ok because our optimizations never make the code
  23.  *         larger than it currently is)
  24.  *
  25.  *    (5) convert JSR x(pc) into a BSR x(pc) if it can be reduced to a byte
  26.  *        offset.
  27.  *
  28.  *    note that link/unlk removal is not done in this pass, but in the
  29.  *    full opt pass because removal of link/unlk kills debugging.
  30.  *
  31.  *    WARNING:    forward offsets for labels not correct since we modify
  32.  *            instructions, but can be considered a worst case range.
  33.  *
  34.  *    WARNING:    when using GetOpByName() remember that there may be
  35.  *            sequential opcodes with the same name and different
  36.  *            formats.
  37.  */
  38.  
  39. #include "defs.h"
  40.  
  41. Prototype void    PassC(void);
  42.  
  43. void
  44. PassC()
  45. {
  46.     MachCtx **pmc;
  47.     MachCtx *mc;
  48.     OpCod   *oc;
  49.     long i;
  50.     long addr = 0;
  51.     long lost = 0;    /*  # bytes of code *deleted* so far */
  52.     MachCtx *lsb = NULL;
  53.     EffAddr *ea;
  54.  
  55.     pmc = MBase;
  56.     for (i = 0; i < MLines; ++i, ++pmc) {
  57.     mc = *pmc;
  58.     LineNo = mc->LineNo;
  59.     if (mc->Label) {
  60.         if (lsb && mc->Label == lsb->Oper1.Label1 && addr == lsb->m_Addr + 2 && lsb->Oper1.Mode1 == AB_BBRANCH && lsb->OpCode->Id != OpBSR) {
  61.         /*
  62.          *  branch to next location... backup, delete it, continue on (handles multiple deletes)
  63.          */
  64.         if (Verbose)
  65.             cerror(EVERBOSE_REMOVED_BRANCH_NEXT);
  66.         while (i >= 0 && lsb != *pmc) {
  67.             --i;
  68.             --pmc;
  69.         }
  70.         if (i < 0)
  71.             cerror(ESOFT_BRANCH_OPT);
  72.         lsb->OpCode = NULL;
  73.         addr = lsb->m_Addr;
  74.         lost += 2;
  75.  
  76.         /*
  77.          *  find previous inst.. if a branch set lsb to that.
  78.          *  Ignore DEBUG pseudoops which do not insert any code
  79.          */
  80.         {
  81.             MachCtx **ppmc = pmc;
  82.             long ii = i;
  83.             while (i >= 0 && ((*ppmc)->OpCode == NULL || (*ppmc)->OpCode->Id == OdDEBUG)) {
  84.             --ii;
  85.             --ppmc;
  86.             }
  87.             if (ii >= 0)
  88.             lsb = *ppmc;
  89.         }
  90.         continue;
  91.         }
  92.         mc->Label->l_Offset = addr;
  93.     }
  94.     mc->m_Addr = addr;
  95.     if ((oc = mc->OpCode) == NULL)
  96.         continue;
  97.     if (oc->Id < 0) {
  98.         addr = ExecOpCodeC(mc, addr);
  99.         continue;
  100.     }
  101.  
  102.     switch(oc->Id) {
  103.     case OpMOVEM:                /*  MOVEM optimization */
  104.         if (mc->Oper1.Mode1 == AB_REGS)
  105.         ea = &mc->Oper1;
  106.         else
  107.         ea = &mc->Oper2;
  108.         if (ea->Label1 && ea->Label1->l_Type == LT_REG) {
  109.         if (ea->ExtWord == 0) {
  110.             mc->OpCode = NULL;        /*  delete inst  */
  111.             lost += 4;
  112.             continue;
  113.         }
  114.         if (ea->Reg1 >= 0)  {   /*  just one reg.. -> MOVE */
  115.             if (ea->ExtWord & ~(1 << ea->Reg1))
  116.             cerror(ESOFT_BAD_MASK_REG, ea->Reg1, ea->ExtWord);
  117.             mc->OpCode = oc = GetOpByName("MOVE");
  118.             if (ea->Reg1 >= RB_AREG) {
  119.             if (ea == &mc->Oper2)
  120.                 mc->OpCode = oc = GetOpByName("MOVEA");
  121.             ea->Mode1 = AB_AN;
  122.             } else {
  123.             ea->Mode1 = AB_DN;
  124.             }
  125.             lost += 2;
  126.             ea->Label1 = NULL;
  127.         }
  128.         }
  129.         break;
  130.     case OpJSR:                /*  JSR optimization    */
  131.         /*
  132.          *    convert a pc-relative JSR to BSR.W (easy to do since no
  133.          *    change in instruction size)
  134.          */
  135.         if (mc->Oper1.Mode1 != AB_OFFPC)
  136.         break;
  137.         oc -= 2;
  138.         mc->OpCode = oc;
  139.         mc->Oper1.Mode1 = AB_WBRANCH;
  140.         mc->OpSize = 0;
  141.         /* fall through */
  142.     case OpBCC:                /*  BRANCH optimization */
  143.     case OpBCS:
  144.     case OpBEQ:
  145.     case OpBGE:
  146.     case OpBGT:
  147.     case OpBHI:
  148.     case OpBLE:
  149.     case OpBLS:
  150.     case OpBLT:
  151.     case OpBMI:
  152.     case OpBNE:
  153.     case OpBPL:
  154.     case OpBVC:
  155.     case OpBVS:
  156.     case OpBRA:
  157.     case OpBSR:
  158.         if (mc->Oper1.Offset1 == 0) {
  159.         Label *lab;
  160.         long cnt = 20;    /*  handle loops */
  161.  
  162.         while ((lab = mc->Oper1.Label1) && lab->l_Type == LT_LOC && lab->Sect == CurSection && cnt--) {
  163.             MachCtx **ppmc = lab->MC;
  164.             MachCtx *xmc;
  165.  
  166.             while (*ppmc && (*ppmc)->OpCode == NULL)    /*  skip nothings   */
  167.             ++ppmc;
  168.             if ((xmc = *ppmc) == NULL)                  /*  end of assembly */
  169.             break;
  170.             if (xmc->Sect == CurSection && xmc->OpCode->Id == OpBRA) {            /*  branch to branch */
  171.             if (mc == xmc)                          /*  bra to self..   */
  172.                 break;
  173.             mc->Oper1.Label1 = xmc->Oper1.Label1;
  174.             if (Verbose)
  175.                 cerror(EVERBOSE_BRANCH_BRANCH);
  176.             continue;
  177.             }
  178.  
  179.             /*
  180.              *    mc label is local.
  181.              *        (1) remove branch entirely if it
  182.              *        branches to the next loc... (actually done
  183.              *        at top of loop)
  184.              *
  185.              *        (2) optimize to byte branch if poss.  note: will not
  186.              *        know about bra-to-next-addr until later.
  187.              *
  188.              *
  189.              *        When optimizing branches we must take into account
  190.              *        the difference in PC and actual PC.. the 'lost'
  191.              *        variable, due to removing previous instructions and
  192.              *        the l_Offset's of later ones being wrong by 'lost'
  193.              *        bytes.
  194.              */
  195.  
  196.             if (mc->OpSize == 0) {
  197.             long range = mc->Oper1.Label1->l_Offset - (addr + 2);
  198.  
  199.             if (mc->Oper1.Label1->l_Offset > (addr + 2))
  200.                 range -= lost;
  201.  
  202.             /*
  203.              *  hack hack hack. need to convert to byte
  204.              *  branch for instruction deletion but can't
  205.              *  delete BSR's so must be sure we do not convert
  206.              *  to a BSR to the next instruction
  207.              */
  208.  
  209.             if (range >= -126 && range < 126 && range) {
  210.                 if (oc->SModes & AF_WBRANCH) {
  211.                 if (range != 2 || oc->Id != OpBSR) {
  212.                     mc->OpCode = ++oc;
  213.                     mc->Oper1.Mode1 = AB_BBRANCH;
  214.                     lost += 2;
  215.                 }
  216.                 }
  217.             } else {
  218.                 if (oc->SModes & AF_BBRANCH) {
  219.                 mc->OpCode = --oc;
  220.                 mc->Oper1.Mode1 = AB_WBRANCH;
  221.                 lost -= 2;
  222.                 }
  223.             }
  224.             lsb = mc;
  225.             }
  226.             break;
  227.         }
  228.         }
  229.         break;
  230.     case OpLINK:
  231.         if (Optimize >= 1) {
  232.         if ((GetFlags() & ~MF_CALLMADE) == 0 && mc->Oper1.Label1 == NULL && mc->Oper1.Offset1 == 0) {
  233.             lost += 4;
  234.             mc->OpCode = NULL;        /*  delete inst  */
  235.             continue;
  236.         } else {
  237.             SetA5UsedFlag();
  238.         }
  239.         }
  240.         break;
  241.     case OpUNLK:
  242.         if (Optimize >= 1) {
  243.         if ((GetFlags() & ~MF_CALLMADE) == 0) {
  244.             lost += 2;
  245.             mc->OpCode = NULL;
  246.             continue;
  247.         }
  248.         }
  249.         break;
  250.     default:
  251.         lsb = NULL; /*  efficiency boost, not reqd */
  252.     }
  253.     addr += GetInstSize(mc);
  254.     }
  255. }
  256.  
  257.  
  258.  
  259.